package ua.yandex.shad.tempseries;

public class TemperatureSeriesAnalysis {

    static final int MIN_CELSIUS = -273;
    private final double[] temperatureSeries;

    private boolean isTemperatureSeriesNull() {
        return this.temperatureSeries == null;
    }

    private boolean isTemperatureSeriesLengthZero() {
        return this.temperatureSeries.length == 0;
    }

    public TemperatureSeriesAnalysis(final double[] temperatureSeries) {
        if (temperatureSeries == null) {
            this.temperatureSeries = null;
        } else {
            for (int i = 0; i <= temperatureSeries.length - 1; i++) {
                if (temperatureSeries[i] <= MIN_CELSIUS) {
                    throw new IllegalArgumentException("Les than -273");
                }
            }

            this.temperatureSeries = temperatureSeries;
        }
    }

    final double calcAverageTemp() {
        double average = 0;
        if (this.isTemperatureSeriesNull()
                || this.isTemperatureSeriesLengthZero()) {
            return 0;
        }
        for (int i = 0; i <= this.temperatureSeries.length - 1; i++) {
            average = average + this.temperatureSeries[i];
        }
        average = average / this.temperatureSeries.length;
        return average;
    }

    final double calcTempDeviation() {
        double dev = 0;
        if (this.isTemperatureSeriesNull()) {
            return 0;
        } else if (this.isTemperatureSeriesLengthZero()) {
            return 0;
        }
        double aver = this.calcAverageTemp();
        for (int i = 0; i <= this.temperatureSeries.length - 1; i++) {
            dev = dev + Math.pow(this.temperatureSeries[i] - aver, 2);
        }
        dev = dev / this.temperatureSeries.length;
        return dev;
    }

    final double findTempClosestToZero() {
        return this.findTempClosestToValue(0);
    }

    final double absDiff(final double temperature, final double compTemperature) {

        return Math.abs(temperature - compTemperature);
    }

    final double findTempClosestToValue(final double tempValue) {
        double absmin;
        double min;
        if (this.isTemperatureSeriesNull()) {
            return 0;
        } else if (this.isTemperatureSeriesLengthZero()) {
            return 0;
        }
        absmin = Math.abs(this.temperatureSeries[0] - tempValue);
        min = this.temperatureSeries[0];
        for (int i = 0; i <= this.temperatureSeries.length - 1; i++) {
            double locTemper = this.temperatureSeries[i];
            if (absmin > Math.abs(locTemper - tempValue)) {
                absmin = Math.abs(locTemper - tempValue);
                min = locTemper;
            } else if (absmin == absDiff(locTemper, tempValue) && min < locTemper) {

                min = this.temperatureSeries[i];

            }
        }
        return min;
    }

    final double[] findTempsLessThen(final double tempValue) {
        double[] ret = new double[1];
        ret[0] = 0;
        if (this.isTemperatureSeriesNull()) {
            return ret;
        } else if (this.isTemperatureSeriesLengthZero()) {
            return ret;
        }
        int j = 0;
        double[] lessTemp = new double[this.temperatureSeries.length + 1];

        for (int i = 0; i <= this.temperatureSeries.length - 1; i++) {
            if (this.temperatureSeries[i] < tempValue) {
                j++;
                lessTemp[j - 1] = this.temperatureSeries[i];
            }
        }
        double[] lessTempSwap = new double[j];
        for (int i = 0; i <= j - 1; i++) {
            lessTempSwap[i] = lessTemp[i];
        }
        if (lessTempSwap.length == 0) {
            lessTemp = new double[1];
            lessTemp[0] = 0;
            return lessTemp;
        }
        return lessTempSwap;
    }

    final double[] findTempsGreaterThen(final double tempValue) {
        double[] ret = new double[1];
        ret[0] = 0;
        if (this.isTemperatureSeriesNull()) {
            return ret;
        } else if (this.isTemperatureSeriesLengthZero()) {
            return ret;
        }
        int j = 0;
        double[] lessTemp = new double[this.temperatureSeries.length + 1];
        for (int i = 0; i <= this.temperatureSeries.length - 1; i++) {
            if (this.temperatureSeries[i] >= tempValue) {
                j++;
                lessTemp[j - 1] = this.temperatureSeries[i];
            }
        }
        double[] lessTempSwap = new double[j];
        for (int i = 0; i <= j - 1; i++) {
            lessTempSwap[i] = lessTemp[i];
        }
        if (lessTempSwap.length == 0) {
            lessTemp = new double[1];
            lessTemp[0] = 0;
            return lessTemp;
        }
        return lessTempSwap;
    }
}
